home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 1 / QRZ Ham Radio Callsign Database - December 1993.iso / ucsd / packet / tcpip / amiga / asrc29k.lha / nrcmd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-01-08  |  22.7 KB  |  1,009 lines

  1. /* net/rom user command processing
  2.  * Copyright 1989 by Daniel M. Frank, W9NK.  Permission granted for
  3.  * non-commercial distribution only.
  4.  */
  5.  
  6. #include <stdio.h>
  7. #include <ctype.h>
  8. #include "global.h"
  9. #include "mbuf.h"
  10. #include "ax25.h"
  11. #include "mailbox.h"
  12. #include "netrom.h"
  13. #include "nr4.h"
  14. #include "timer.h"
  15. #include "iface.h"
  16. #include "lapb.h"
  17. #include "cmdparse.h"
  18. #include "session.h"
  19. #include "socket.h"
  20. #include "commands.h"
  21. #include "config.h"
  22.  
  23. #ifdef    MAILBOX
  24. static int Nrsocket = -1;
  25. #endif
  26.  
  27. char Nr4user[AXALEN];
  28.  
  29. char *Nr4states[] = {
  30.     "Disconnected",
  31.     "Conn Pending",
  32.     "Connected",
  33.     "Disc Pending",
  34.     "Listening"
  35. } ;
  36.  
  37. char *Nr4reasons[] = {
  38.     "Normal",
  39.     "By Peer",
  40.     "Timeout",
  41.     "Reset",
  42.     "Refused"
  43. } ;
  44.  
  45. static int dobcnodes __ARGS((int argc,char *argv[],void *p));
  46. static int dointerface __ARGS((int argc,char *argv[],void *p));
  47. static int donfadd __ARGS((int argc,char *argv[],void *p));
  48. static int donfdrop __ARGS((int argc,char *argv[],void *p));
  49. static int donfdump __ARGS((void));
  50. static int donfmode __ARGS((int argc,char *argv[],void *p));
  51. static int donodefilter __ARGS((int argc,char *argv[],void *p));
  52. static void donodetick __ARGS((void));
  53. static int donodetimer __ARGS((int argc,char *argv[],void *p));
  54. static int donracktime __ARGS((int argc,char *argv[],void *p));
  55. static int donrchoketime __ARGS((int argc,char *argv[],void *p));
  56. static int donrconnect __ARGS((int argc,char *argv[],void *p));
  57. static int donrirtt __ARGS((int argc,char *argv[],void *p));
  58. static int donrkick __ARGS((int argc,char *argv[],void *p));
  59. static int dorouteadd __ARGS((int argc,char *argv[],void *p));
  60. static int doroutedrop __ARGS((int argc,char *argv[],void *p));
  61. static int donrqlimit __ARGS((int argc,char *argv[],void *p));
  62. static int donrreset __ARGS((int argc,char *argv[],void *p));
  63. static int donrretries __ARGS((int argc,char *argv[],void *p));
  64. static int donrroute __ARGS((int argc,char *argv[],void *p));
  65. static int donrstatus __ARGS((int argc,char *argv[],void *p));
  66. static int donrttl __ARGS((int argc,char *argv[],void *p));
  67. static int donrtype __ARGS((int argc,char *argv[],void *p));
  68. static int donruser __ARGS((int argc,char *argv[],void *p));
  69. static int donrverbose __ARGS((int argc,char *argv[],void *p));
  70. static int donrwindow __ARGS((int argc,char *argv[],void *p));
  71. static void doobsotick __ARGS((void));
  72. static int doobsotimer __ARGS((int argc,char *argv[],void *p));
  73.  
  74. static struct cmds Nrcmds[] = {
  75.     "acktime",    donracktime,    0, 0,    NULLCHAR,
  76.     "bcnodes",    dobcnodes,    0, 2,    "netrom bcnodes <interface>",
  77.     "connect",    donrconnect, 1024, 2,    "netrom connect <node>",
  78.     "choketime",    donrchoketime,    0, 0,    NULLCHAR,
  79.     "interface",    dointerface,    0, 4,
  80.         "netrom interface <interface> <alias> <quality>",
  81.     "irtt",        donrirtt,    0, 0,    NULLCHAR,
  82.     "kick",        donrkick,    0, 2,    "netrom kick <&nrcb>",
  83.     "nodefilter",    donodefilter,    0, 0,    NULLCHAR,
  84.     "nodetimer",    donodetimer,    0, 0,    NULLCHAR,
  85.     "obsotimer",    doobsotimer,    0, 0,    NULLCHAR,
  86.     "qlimit",    donrqlimit,    0, 0,    NULLCHAR,
  87.     "reset",    donrreset,    0, 2,    "netrom reset <&nrcb>",
  88.     "retries",    donrretries,    0, 0,    NULLCHAR,
  89.     "route",    donrroute,    0, 0,    NULLCHAR,
  90.     "status",    donrstatus,    0, 0,    NULLCHAR,
  91.     "timertype",    donrtype,    0, 0,    NULLCHAR,
  92.     "ttl",        donrttl,    0, 0,    NULLCHAR,
  93.     "user",        donruser,    0, 0,    NULLCHAR,
  94.     "verbose",    donrverbose,    0, 0,    NULLCHAR,
  95.     "window",    donrwindow,    0, 0,    NULLCHAR,
  96.     NULLCHAR,
  97. } ;
  98.  
  99. static struct timer Nodetimer ;    /* timer for nodes broadcasts */
  100. static struct timer Obsotimer ;    /* timer for aging routes */
  101.  
  102. /* Command multiplexer */
  103. int donetrom(argc,argv,p)
  104. int argc ;
  105. char *argv[] ;
  106. void *p;
  107. {
  108.     if(argc == 1)
  109.         return donrroute(argc,argv,p);
  110.     return subcmd(Nrcmds,argc,argv,p) ;
  111. }
  112.  
  113. static struct cmds Routecmds[] = {
  114.     "add",    dorouteadd,    0, 6,
  115.         "netrom route add <alias> <destination> <interface> <quality> <neighbor>",
  116.     "drop",    doroutedrop, 0, 4,
  117.         "netrom route drop <destination> <neighbor> <interface>",
  118.     "info", dorouteinfo, 0, 2,
  119.         "netrom route info <destination>",
  120.     NULLCHAR,
  121. } ;
  122.  
  123. /* Route command multiplexer */
  124. static int donrroute(argc, argv,p)
  125. int argc ;
  126. char *argv[] ;
  127. void *p;
  128. {
  129.     if (argc < 2) {
  130.         doroutedump() ;
  131.         return 0 ;
  132.     }
  133.     return subcmd(Routecmds,argc,argv,p) ;
  134. }
  135.  
  136. /* Dump a list of known routes */
  137. int doroutedump()
  138. {
  139.     register struct nrroute_tab *rp ;
  140.     register int i, column ;
  141.     char buf[16] ;
  142.     char *cp ;
  143.     
  144.     column = 1 ;
  145.     
  146.     for (i = 0 ; i < NRNUMCHAINS ; i++)
  147.         for (rp = Nrroute_tab[i] ; rp != NULLNRRTAB ; rp = rp->next) {
  148.             strcpy(buf,rp->alias) ;
  149.             /* remove trailing spaces */
  150.             if ((cp = strchr(buf,' ')) == NULLCHAR)
  151.                 cp = &buf[strlen(buf)] ;
  152.             if (cp != buf)        /* don't include colon for null alias */
  153.                 *cp++ = ':' ;
  154.             pax25(cp,rp->call) ;
  155.             tprintf("%-16s  ",buf) ;
  156.             if (column++ == 4) {
  157.                 if(tprintf("\n") == EOF)
  158.                     return 0;
  159.                 column = 1 ;
  160.             }
  161.         }
  162.  
  163.     if (column != 1)
  164.         tprintf("\n") ;
  165.         
  166.     return 0 ;
  167. }
  168.  
  169. /* print detailed information on an individual route */
  170. int dorouteinfo(argc,argv,p)
  171. int argc ;
  172. char *argv[] ;
  173. void *p;
  174. {
  175.     register struct nrroute_tab *rp ;
  176.     register struct nr_bind *bp ;
  177.     register struct nrnbr_tab *np ;
  178.     char dest[AXALEN] ;
  179.     char neighbor[AXBUF] ;
  180.  
  181.     if (setcall(dest,argv[1]) == -1) {
  182.         tprintf ("bad destination name\n") ;
  183.         return -1 ;
  184.     }
  185.         
  186.     if ((rp = find_nrroute(dest)) == NULLNRRTAB) {
  187.         tprintf("no such route\n") ;
  188.         return -1 ;
  189.     }
  190.  
  191.     for (bp = rp->routes ; bp != NULLNRBIND ; bp = bp->next) {
  192.         np = bp->via ;
  193.         if(tprintf("%1s %3d  %3d  %-8s  %s\n",
  194.          (bp->flags & NRB_PERMANENT ? "P" :
  195.          bp->flags & NRB_RECORDED ? "R" : " "),
  196.          bp->quality,bp->obsocnt,
  197.          Nrifaces[np->iface].iface->name,
  198.          pax25(neighbor,np->call)) == EOF)
  199.             break;
  200.     }
  201.     return 0 ;
  202. }
  203.  
  204. /* convert a null-terminated alias name to a blank-filled, upcased */
  205. /* version.  Return -1 on failure. */
  206. int putalias(to,from,complain)
  207. register char *to, *from ;
  208. int complain ;    
  209. {
  210.     int len, i ;
  211.     
  212.     if ((len = strlen(from)) > ALEN) {
  213.         if (complain)
  214.             tprintf ("alias too long - six characters max\n") ;
  215.         return -1 ;
  216.     }
  217.     
  218.     for (i = 0 ; i < ALEN ; *to++, *from++, i++) 
  219.         if (i < len) 
  220.             *to = toupper(*from) ;
  221.         else
  222.             *to = ' ' ;
  223.  
  224.     *to = '\0' ;
  225.     return 0 ;
  226. }
  227.  
  228. /* Add a route */
  229. static int dorouteadd(argc, argv,p)
  230. int argc ;
  231. char *argv[] ;
  232. void *p;
  233. {
  234.     char alias[AXALEN] ;
  235.     char dest[AXALEN] ;
  236.     unsigned quality ;
  237.     char neighbor[AXALEN] ;
  238.     register int i ;
  239.     int naddr ;
  240.  
  241.     /* format alias (putalias prints error message if necessary) */
  242.     if (putalias(alias,argv[1],1) == -1)
  243.         return -1 ;
  244.  
  245.     /* format destination callsign */
  246.     if (setcall(dest,argv[2]) == -1) {
  247.         tprintf("bad destination callsign\n") ;
  248.         return -1 ;
  249.     }
  250.  
  251.     /* find interface */
  252.     for (i = 0 ; i < Nr_numiface ; i++)
  253.         if (!strcmp(Nrifaces[i].iface->name,argv[3]))
  254.             break ;
  255.     if (i == Nr_numiface) {
  256.         tprintf("Interface \"%s\" not found\n",argv[3]) ;
  257.         return -1 ;
  258.     }
  259.     
  260.     /* get and check quality value */
  261.     if ((quality = atoi(argv[4])) > 255) {
  262.         tprintf("maximum route quality is 255\n") ;
  263.         return -1 ;
  264.     }
  265.  
  266.     /* Change from 871225 -- no digis in net/rom table */
  267.     naddr = argc - 5 ;
  268.     if (naddr > 1) {
  269.         tprintf("Use the ax25 route command to specify digipeaters\n") ;
  270.         return -1 ;
  271.     }
  272.     
  273.     /* format neighbor address string */
  274.     setcall(neighbor,argv[5]) ;
  275.  
  276.     return nr_routeadd(alias,dest,i,quality,neighbor,1,0) ;
  277. }
  278.  
  279.  
  280. /* drop a route */
  281. static int doroutedrop(argc,argv,p)
  282. int argc ;
  283. char *argv[] ;
  284. void *p;
  285. {
  286.     char dest[AXALEN], neighbor[AXALEN] ;
  287.     register int i ;
  288.  
  289.     /* format destination and neighbor callsigns */
  290.     if (setcall(dest,argv[1]) == -1) {
  291.         tprintf("bad destination callsign\n") ;
  292.         return -1 ;
  293.     }
  294.     if (setcall(neighbor,argv[2]) == -1) {
  295.         tprintf("bad neighbor callsign\n") ;
  296.         return -1 ;
  297.     }
  298.  
  299.     /* find interface */
  300.     for (i = 0 ; i < Nr_numiface ; i++)
  301.         if (!strcmp(Nrifaces[i].iface->name,argv[3]))
  302.             break ;
  303.     if (i == Nr_numiface) {
  304.         tprintf("Interface \"%s\" not found\n",argv[3]) ;
  305.         return -1 ;
  306.     }
  307.  
  308.     return nr_routedrop(dest,neighbor,i) ;
  309. }
  310.     
  311.     
  312. /* make an interface available to net/rom */
  313. static int dointerface(argc,argv,p)
  314. int argc ;
  315. char *argv[] ;
  316. void *p;
  317. {
  318.     int i ;
  319.     register struct iface *ifp ;
  320.  
  321.     if (Nr_iface == NULLIF) {
  322.         tprintf("Attach netrom interface first\n") ;
  323.         return 1 ;
  324.     }
  325.     
  326.     if (Nr_numiface >= NRNUMIFACE) {
  327.         tprintf("Only %d net/rom interfaces available\n",NRNUMIFACE) ;
  328.         return 1 ;
  329.     }
  330.     
  331.     if((ifp = if_lookup(argv[1])) == NULLIF){
  332.         tprintf(Badinterface,argv[1]);
  333.         return 1;
  334.     }
  335.     for (i = 0 ; i < Nr_numiface ; i++)
  336.         if (Nrifaces[i].iface == ifp) {
  337.             tprintf("Interface \"%s\" is already registered\n",argv[1]) ;
  338.             return 1 ;
  339.         }
  340.         
  341.     Nrifaces[Nr_numiface].iface = ifp ;
  342.  
  343.     if (putalias(Nrifaces[Nr_numiface].alias,argv[2],1) == -1)
  344.         return 1 ;
  345.         
  346.     if ((Nrifaces[Nr_numiface].quality = atoi(argv[3])) > 255) {
  347.         tprintf("Quality cannot be greater than 255\n") ;
  348.         return 1 ;
  349.     }
  350.         
  351.     Nr_numiface++ ;            /* accept this interface */
  352.     return 0 ;
  353. }
  354.  
  355. /* Broadcast nodes list on named interface. */
  356. static int dobcnodes(argc,argv,p)
  357. int argc ;
  358. char *argv[] ;
  359. void *p;
  360. {
  361.     register int i ;
  362.  
  363.     for (i = 0 ; i < Nr_numiface ; i++)
  364.         if (!strcmp(Nrifaces[i].iface->name,argv[1]))
  365.             break ;
  366.     if (i == Nr_numiface) {
  367.         tprintf("Interface \"%s\" not found\n",argv[1]) ;
  368.         return 1 ;
  369.     }
  370.         
  371.     nr_bcnodes(i) ;
  372.     return 0;
  373. }
  374.  
  375. #define TICKSPERSEC    (1000L / MSPTICK)    /* Ticks per second */
  376.  
  377. /* Set outbound node broadcast interval */
  378. static int donodetimer(argc,argv,p)
  379. int argc;
  380. char *argv[];
  381. void *p;
  382. {
  383.     if(argc < 2){
  384.         tprintf("Nodetimer %lu/%lu seconds\n",
  385.             read_timer(&Nodetimer)/TICKSPERSEC,
  386.             dur_timer(&Nodetimer)/TICKSPERSEC);
  387.         return 0;
  388.     }
  389.     stop_timer(&Nodetimer) ;    /* in case it's already running */
  390.     Nodetimer.func = (void (*)())donodetick;/* what to call on timeout */
  391.     Nodetimer.arg = NULLCHAR;        /* dummy value */
  392.     Nodetimer.start = atoi(argv[1])*TICKSPERSEC;    /* set timer duration */
  393.     start_timer(&Nodetimer);        /* and fire it up */
  394.     return 0;
  395. }
  396.  
  397. static void donodetick()
  398. {
  399.     register int i ;
  400.  
  401.     for (i = 0 ; i < Nr_numiface ; i++)
  402.         nr_bcnodes(i) ;
  403.  
  404.     /* Restart timer */
  405.     start_timer(&Nodetimer) ;
  406. }
  407.  
  408. /* Set timer for aging routes */
  409. static int doobsotimer(argc,argv,p)
  410. int argc;
  411. char *argv[];
  412. void *p;
  413. {
  414.     if(argc < 2){
  415.         tprintf("Obsotimer %lu/%lu seconds\n",
  416.             read_timer(&Obsotimer)/TICKSPERSEC,
  417.             dur_timer(&Obsotimer)/TICKSPERSEC);
  418.         return 0;
  419.     }
  420.     stop_timer(&Obsotimer) ;    /* just in case it's already running */
  421.     Obsotimer.func = (void (*)())doobsotick;/* what to call on timeout */
  422.     Obsotimer.arg = NULLCHAR;        /* dummy value */
  423.     Obsotimer.start = atoi(argv[1])*TICKSPERSEC;    /* set timer duration */
  424.     start_timer(&Obsotimer);        /* and fire it up */
  425.     return 0;
  426. }
  427.  
  428.  
  429. /* Go through the routing table, reducing the obsolescence count of
  430.  * non-permanent routes, and purging them if the count reaches 0
  431.  */
  432. static void doobsotick()
  433. {
  434.     register struct nrnbr_tab *np ;
  435.     register struct nrroute_tab *rp, *rpnext ;
  436.     register struct nr_bind *bp, *bpnext ;
  437.     int i ;
  438.  
  439.     for (i = 0 ; i < NRNUMCHAINS ; i++) {
  440.         for (rp = Nrroute_tab[i] ; rp != NULLNRRTAB ; rp = rpnext) {
  441.             rpnext = rp->next ;     /* save in case we free this route */
  442.             for (bp = rp->routes ; bp != NULLNRBIND ; bp = bpnext) {
  443.                 bpnext = bp->next ;    /* in case we free this binding */
  444.                 if (bp->flags & NRB_PERMANENT)    /* don't age these */
  445.                     continue ;
  446.                 if (--bp->obsocnt == 0) {        /* time's up! */
  447.                     if (bp->next != NULLNRBIND)
  448.                         bp->next->prev = bp->prev ;
  449.                     if (bp->prev != NULLNRBIND)
  450.                         bp->prev->next = bp->next ;
  451.                     else
  452.                         rp->routes = bp->next ;
  453.                     rp->num_routes-- ;            /* one less binding */
  454.                     np = bp->via ;                /* find the neighbor */
  455.                     free((char *)bp) ;                /* now we can free the bind */
  456.                     /* Check to see if we can free the neighbor */
  457.                     if (--np->refcnt == 0) {
  458.                         if (np->next != NULLNTAB)
  459.                             np->next->prev = np->prev ;
  460.                         if (np->prev != NULLNTAB)
  461.                             np->prev->next = np->next ;
  462.                         else {
  463.                             Nrnbr_tab[nrhash(np->call)] = np->next ;
  464.                         }
  465.                         free((char *)np) ;    /* free the storage */
  466.                     }
  467.                 }
  468.             }
  469.             if (rp->num_routes == 0) {        /* did we free them all? */
  470.                 if (rp->next != NULLNRRTAB)
  471.                     rp->next->prev = rp->prev ;
  472.                 if (rp->prev != NULLNRRTAB)
  473.                     rp->prev->next = rp->next ;
  474.                 else
  475.                     Nrroute_tab[i] = rp->next ;
  476.  
  477.                 free((char *)rp) ;
  478.             }
  479.         }
  480.     }
  481.  
  482.     start_timer(&Obsotimer) ;
  483. }
  484.  
  485. static struct cmds Nfcmds[] = {
  486.     "add",    donfadd,    0, 3,
  487.         "netrom nodefilter add <neighbor> <interface>",
  488.     "drop",    donfdrop,    0, 3,
  489.         "netrom nodefilter drop <neighbor> <interface>",
  490.     "mode",    donfmode,    0, 0,    NULLCHAR,
  491.     NULLCHAR,    NULLFP,    0, 0,
  492.         "nodefilter subcommands: add drop mode",
  493. } ;
  494.  
  495. /* nodefilter command multiplexer */
  496. static int donodefilter(argc,argv,p)
  497. int argc ;
  498. char *argv[] ;
  499. void *p;
  500. {
  501.     if (argc < 2) {
  502.         donfdump() ;
  503.         return 0 ;
  504.     }
  505.     return subcmd(Nfcmds,argc,argv,p) ;
  506. }
  507.  
  508. /* display a list of <callsign,interface> pairs from the filter
  509.  * list.
  510.  */
  511. static int donfdump()
  512. {
  513.     int i, column = 1 ;
  514.     struct nrnf_tab *fp ;
  515.     char buf[16] ;
  516.  
  517.     for (i = 0 ; i < NRNUMCHAINS ; i++)
  518.         for (fp = Nrnf_tab[i] ; fp != NULLNRNFTAB ; fp = fp->next) {
  519.             pax25(buf,fp->neighbor) ;
  520.             tprintf("%-7s %-8s  ",
  521.              buf,Nrifaces[fp->iface].iface->name) ;
  522.             if (column++ == 4) {
  523.                 if(tprintf("\n") == EOF)
  524.                     return 0;
  525.                 column = 1 ;
  526.             }
  527.         }
  528.  
  529.     if (column != 1)
  530.         tprintf("\n") ;
  531.  
  532.     return 0 ;
  533. }
  534.  
  535. /* add an entry to the filter table */
  536. static int donfadd(argc,argv,p)
  537. int argc ;
  538. char *argv[] ;
  539. void *p;
  540. {
  541.     char neighbor[AXALEN] ;
  542.     register int i ;
  543.  
  544.     /* format callsign */
  545.     if (setcall(neighbor,argv[1]) == -1) {
  546.         tprintf("bad neighbor callsign\n") ;
  547.         return -1 ;
  548.     }
  549.  
  550.     /* find interface */
  551.     for (i = 0 ; i < Nr_numiface ; i++)
  552.         if (!strcmp(Nrifaces[i].iface->name,argv[2]))
  553.             break ;
  554.     if (i == Nr_numiface) {
  555.         tprintf("Interface \"%s\" not found\n",argv[2]) ;
  556.         return -1 ;
  557.     }
  558.  
  559.     return nr_nfadd(neighbor,i) ;
  560. }
  561.  
  562. /* drop an entry from the filter table */
  563. static int donfdrop(argc,argv,p)
  564. int argc ;
  565. char *argv[] ;
  566. void *p;
  567. {
  568.     char neighbor[AXALEN] ;
  569.     register int i ;
  570.  
  571.     /* format neighbor callsign */
  572.     if (setcall(neighbor,argv[1]) == -1) {
  573.         tprintf("bad neighbor callsign\n") ;
  574.         return -1 ;
  575.     }
  576.  
  577.     /* find interface */
  578.     for (i = 0 ; i < Nr_numiface ; i++)
  579.         if (!strcmp(Nrifaces[i].iface->name,argv[2]))
  580.             break ;
  581.     if (i == Nr_numiface) {
  582.         tprintf("Interface \"%s\" not found\n",argv[2]) ;
  583.         return -1 ;
  584.     }
  585.  
  586.     return nr_nfdrop(neighbor,i) ;
  587. }
  588.  
  589. /* nodefilter mode subcommand */
  590. static int donfmode(argc,argv,p)
  591. int argc ;
  592. char *argv[] ;
  593. void *p;
  594. {
  595.     if (argc < 2) {
  596.         tprintf("filter mode is ") ;
  597.         switch (Nr_nfmode) {
  598.             case NRNF_NOFILTER:
  599.                 tprintf("none\n") ;
  600.                 break ;
  601.             case NRNF_ACCEPT:
  602.                 tprintf("accept\n") ;
  603.                 break ;
  604.             case NRNF_REJECT:
  605.                 tprintf("reject\n") ;
  606.                 break ;
  607.             default:
  608.                 tprintf("some strange, unknown value\n") ;
  609.         }
  610.         return 0 ;
  611.     }
  612.     
  613.     switch (argv[1][0]) {
  614.         case 'n':
  615.         case 'N':
  616.             Nr_nfmode = NRNF_NOFILTER ;
  617.             break ;
  618.         case 'a':
  619.         case 'A':
  620.             Nr_nfmode = NRNF_ACCEPT ;
  621.             break ;
  622.         case 'r':
  623.         case 'R':
  624.             Nr_nfmode = NRNF_REJECT ;
  625.             break ;
  626.         default:
  627.             tprintf("modes are: none accept reject\n") ;
  628.             return -1 ;
  629.     }
  630.  
  631.     return 0 ;
  632. }
  633.  
  634. /* netrom network packet time-to-live initializer */
  635. static int donrttl(argc, argv,p)
  636. int argc ;
  637. char *argv[] ;
  638. void *p;
  639. {
  640.     return setshort(&Nr_ttl,"Time to live",argc,argv);
  641. }
  642.  
  643. /* verbose route broadcast */
  644. static int donrverbose(argc,argv,p)
  645. int argc ;
  646. char *argv[] ;
  647. void *p;
  648. {
  649.     return setbool(&Nr_verbose,"Verbose flag",argc,argv);
  650. }
  651.  
  652. /* Initiate a NET/ROM transport connection */
  653. static int donrconnect(argc,argv,p)
  654. int argc ;
  655. char *argv[] ;
  656. void *p;
  657. {
  658.     char *np ;
  659.     struct sockaddr_nr lsocket, fsocket;
  660.     char alias[AXBUF];
  661.     struct session *sp;
  662.  
  663.     /* Get a session descriptor */
  664.     if ((sp = newsession(argv[1],NRSESSION)) == NULLSESSION) {
  665.         tprintf("Too many sessions\n") ;
  666.         freeargs(argc,argv);
  667.         return 1 ;
  668.     }
  669.  
  670.     if((sp->s = socket(AF_NETROM,SOCK_SEQPACKET,0)) == -1){
  671.         tprintf("Can't create socket\n");
  672.         freeargs(argc,argv);
  673.         keywait(NULLCHAR,1);
  674.         freesession(sp);
  675.         return 1;
  676.     }
  677.     lsocket.nr_family = AF_NETROM;
  678.     /* Set up our local username, bind would use Mycall instead */
  679.     memcpy(lsocket.nr_addr.user,Nr4user,AXALEN);
  680.     /* Putting anything else than Mycall here will not work */
  681.     memcpy(lsocket.nr_addr.node,Mycall,AXALEN);
  682.     bind(sp->s,(char *)&lsocket,sizeof(struct sockaddr_nr));
  683.  
  684.     /* See if the requested destination could be an alias, and */
  685.     /* find and use it if it is.  Otherwise assume it is an ax.25 */
  686.     /* address. */
  687.     
  688.     if (putalias(alias,argv[1],0) != -1 &&
  689.         (np = find_nralias(alias)) != NULLCHAR) {
  690.         memcpy(fsocket.nr_addr.user,np,AXALEN) ;
  691.         memcpy(fsocket.nr_addr.node,np,AXALEN) ;
  692.     } else {    /* parse ax25 callsign */
  693.         /* Only the user callsign of the remote station is never used by */
  694.         /* NET/ROM, but it is needed for the psocket() call. */
  695.         setcall(fsocket.nr_addr.user,argv[1]);
  696.         setcall(fsocket.nr_addr.node,argv[1]);
  697.     }
  698.     freeargs(argc,argv);
  699.     fsocket.nr_family = AF_NETROM;
  700.     pax25(alias,fsocket.nr_addr.node);
  701.     return tel_connect(sp, (char *)&fsocket, sizeof(struct sockaddr_nr));
  702. }
  703.  
  704. #ifdef    MAILBOX
  705. int nr4start(argc,argv,p)
  706. int argc;
  707. char *argv[];
  708. void *p;
  709. {
  710.     int s,type;
  711.  
  712.     freeargs(argc,argv);
  713.     if (Nrsocket != -1)
  714.         return -1;
  715.  
  716.     psignal(Curproc,0);    /* Don't keep the parser waiting */
  717.     chname(Curproc,"NETROM listener");
  718.     Nrsocket = socket(AF_NETROM,SOCK_SEQPACKET,0);
  719.     /* bind() is done automatically */
  720.     if (listen(Nrsocket,1) == -1) {
  721.         close_s(Nrsocket);
  722.         Nrsocket = -1;
  723.         return -1;
  724.     }
  725.     for(;;){
  726.         if((s = accept(Nrsocket,NULLCHAR,NULLINT)) == -1)
  727.             break;    /* Service is shutting down */
  728.  
  729.         type = NRSESSION;
  730.         newproc("mbox",2048,mbx_incom,s,(void *)&type,NULL);
  731.     }
  732.     close_s(Nrsocket);
  733.     Nrsocket = -1;
  734.     return 0;
  735. }
  736.  
  737. int nr40(argc,argv,p)
  738. int argc;
  739. char *argv[];
  740. void *p;
  741. {
  742.     close_s(Nrsocket);
  743.     Nrsocket = -1;
  744.     return 0;
  745. }
  746. #endif    /* MAILBOX */
  747.  
  748. /* Reset a net/rom connection abruptly */
  749. static int donrreset(argc,argv,p)
  750. int argc;
  751. char *argv[];
  752. void *p;
  753. {
  754.     struct nr4cb *cb ;
  755.  
  756.     cb = (struct nr4cb *)htol(argv[1]);
  757.     if(!nr4valcb(cb)){
  758.         tprintf(Notval);
  759.         return 1;
  760.     }
  761.     reset_nr4(cb);
  762.     return 0;
  763. }
  764.  
  765. /* Force retransmission on a net/rom connection */
  766.  
  767. static int donrkick(argc,argv,p)
  768. int argc;
  769. char *argv[];
  770. void *p;
  771. {
  772.     struct nr4cb *cb ;
  773.  
  774.     cb = (struct nr4cb *)htol(argv[1]);
  775.  
  776.     if (kick_nr4(cb) == -1) {
  777.         tprintf(Notval);
  778.         return 1;
  779.     } else
  780.         return 0;
  781. }
  782.  
  783. /* netrom transport ACK delay timer */
  784. static int donracktime(argc, argv,p)
  785. int argc ;
  786. char *argv[] ;
  787. void *p;
  788. {
  789.     return setlong(&Nr4acktime,"Ack delay time (ms)",argc,argv);
  790. }
  791.  
  792. /* netrom transport choke timeout */
  793. static int donrchoketime(argc, argv,p)
  794. int argc ;
  795. char *argv[] ;
  796. void *p;
  797. {
  798.     return setlong(&Nr4choketime,"Choke timeout (ms)",argc,argv);
  799. }
  800.  
  801. /* netrom transport initial round trip time */
  802.  
  803. static int donrirtt(argc, argv,p)
  804. int argc ;
  805. char *argv[] ;
  806. void *p;
  807. {
  808.     return setlong(&Nr4irtt,"Initial RTT (ms)",argc,argv);
  809. }
  810.  
  811. /* netrom transport receive queue length limit.  This is the */
  812. /* threshhold at which we will CHOKE the sender. */
  813. static int donrqlimit(argc, argv,p)
  814. int argc ;
  815. char *argv[] ;
  816. void *p;
  817. {
  818.     return setshort(&Nr4qlimit,"Queue limit (bytes)",argc,argv);
  819. }
  820.  
  821. /* Display or change our NET/ROM username */
  822. static int donruser(argc,argv,p)
  823. int argc;
  824. char *argv[];
  825. void *p;
  826. {
  827.     char buf[AXBUF];
  828.  
  829.     if(argc < 2){
  830.         pax25(buf,Nr4user);
  831.         tprintf("%s\n",buf);
  832.         return 0;
  833.     }
  834.     if(setcall(Nr4user,argv[1]) == -1)
  835.         return -1;
  836.     Nr4user[ALEN] |= E;
  837.     return 0;
  838. }
  839.  
  840. /* netrom transport maximum window.  This is the largest send and */
  841. /* receive window we may negotiate */
  842. static int donrwindow(argc, argv,p)
  843. int argc ;
  844. char *argv[] ;
  845. void *p;
  846. {
  847.     return setshort(&Nr4window,"Window (frames)",argc,argv);
  848. }
  849.  
  850. /* netrom transport maximum retries.  This is used in connect and */
  851. /* disconnect attempts; I haven't decided what to do about actual */
  852. /* data retries yet. */
  853.  
  854. static int donrretries(argc, argv,p)
  855. int argc ;
  856. char *argv[] ;
  857. void *p;
  858. {
  859.     return setshort(&Nr4retries,"Retry limit",argc,argv);
  860. }
  861.  
  862. /* Display the status of NET/ROM connections */
  863.  
  864. static int donrstatus(argc, argv,p)
  865. int argc ;
  866. char *argv[] ;
  867. void *p;
  868. {
  869.     int i ;
  870.     struct nr4cb *cb ;
  871.     char luser[AXBUF], ruser[AXBUF], node[AXBUF] ;
  872.     
  873.     if (argc < 2) {
  874.         tprintf("     &CB Snd-W Snd-Q Rcv-Q     LUser      RUser @Node     State\n");
  875.         for (i = 0 ; i < NR4MAXCIRC ; i++) {
  876.             if ((cb = Nr4circuits[i].ccb) == NULLNR4CB)
  877.                 continue ;
  878.             pax25(luser,cb->local.user) ;
  879.             pax25(ruser,cb->remote.user) ;
  880.             pax25(node,cb->remote.node) ;
  881.             if(tprintf("%8lx   %3d %5d %5d %9s  %9s %-9s %s\n",
  882.              ptol(cb), cb->nbuffered, len_q(cb->txq),
  883.              len_p(cb->rxq), luser, ruser, node,
  884.              Nr4states[cb->state]) == EOF)
  885.                 break;
  886.         }
  887.         return 0 ;
  888.     }
  889.  
  890.     cb = (struct nr4cb *)htol(argv[1]) ;
  891.     if (!nr4valcb(cb)) {
  892.         tprintf(Notval) ;
  893.         return 1 ;
  894.     }
  895.  
  896.     donrdump(cb) ;
  897.     return 0 ;
  898. }
  899.  
  900. /* Dump one control block */
  901. void donrdump(cb)
  902. struct nr4cb *cb ;
  903. {
  904.     char luser[AXBUF], ruser[AXBUF], node[AXBUF] ;
  905.     unsigned seq ;
  906.     struct nr4txbuf *b ;
  907.     struct timer *t ;
  908.  
  909.     pax25(luser,cb->local.user) ;
  910.     pax25(ruser,cb->remote.user) ;
  911.     pax25(node,cb->remote.node) ;
  912.  
  913.     tprintf("Local: %s %d/%d Remote: %s @ %s %d/%d State: %s\n",
  914.            luser, cb->mynum, cb->myid, ruser, node,
  915.            cb->yournum, cb->yourid, Nr4states[cb->state]) ;
  916.  
  917.     tprintf("Window: %-5u Rxpect: %-5u RxNext: %-5u RxQ: %-5d %s\n",
  918.            cb->window, uchar(cb->rxpected), uchar(cb->rxpastwin),
  919.            len_p(cb->rxq), cb->qfull ? "RxCHOKED" : "") ;
  920.  
  921.     tprintf(" Unack: %-5u Txpect: %-5u TxNext: %-5u TxQ: %-5d %s\n",
  922.            cb->nbuffered, uchar(cb->ackxpected), uchar(cb->nextosend),
  923.            len_q(cb->txq), cb->choked ? "TxCHOKED" : "") ;
  924.  
  925.     tprintf("TACK: ") ;
  926.     if (run_timer(&cb->tack))
  927.         tprintf("%lu", read_timer(&cb->tack) * MSPTICK) ;
  928.     else
  929.         tprintf("stop") ;
  930.     tprintf("/%lu ms; ", dur_timer(&cb->tack) * MSPTICK) ;
  931.  
  932.     tprintf("TChoke: ") ;
  933.     if (run_timer(&cb->tchoke))
  934.         tprintf("%lu", read_timer(&cb->tchoke) * MSPTICK) ;
  935.     else
  936.         tprintf("stop") ;
  937.     tprintf("/%lu ms; ", dur_timer(&cb->tchoke) * MSPTICK) ;
  938.  
  939.     tprintf("TCD: ") ;
  940.     if (run_timer(&cb->tcd))
  941.         tprintf("%lu", read_timer(&cb->tcd) * MSPTICK) ;
  942.     else
  943.         tprintf("stop") ;
  944.     tprintf("/%lu ms", dur_timer(&cb->tcd) * MSPTICK) ;
  945.  
  946.     if (run_timer(&cb->tcd))
  947.         tprintf("; Tries: %u\n", cb->cdtries) ;
  948.     else
  949.         tprintf("\n") ;
  950.  
  951.     tprintf("Backoff Level %u SRTT %ld ms Mean dev %ld ms\n",
  952.            cb->blevel, cb->srtt, cb->mdev) ;
  953.  
  954.     /* If we are connected and the send window is open, display */
  955.     /* the status of all the buffers and their timers */
  956.     
  957.     if (cb->state == NR4STCON && cb->nextosend != cb->ackxpected) {
  958.  
  959.         tprintf("TxBuffers:  Seq  Size  Tries  Timer\n") ;
  960.  
  961.         for (seq = cb->ackxpected ;
  962.              nr4between(cb->ackxpected, seq, cb->nextosend) ;
  963.              seq = (seq + 1) & NR4SEQMASK) {
  964.  
  965.             b = &cb->txbufs[seq % cb->window] ;
  966.             t = &b->tretry ;
  967.  
  968.             if(tprintf("            %3u   %3d  %5d  %lu/%lu\n",
  969.              seq, len_p(b->data), b->retries + 1,
  970.              read_timer(t) * MSPTICK, dur_timer(t) * MSPTICK)
  971.              == EOF)
  972.                 break;
  973.         }
  974.  
  975.     }
  976.  
  977. }
  978.  
  979. /* netrom timers type - linear v exponential */
  980. static donrtype(argc,argv,p)
  981. int argc ;
  982. char *argv[] ;
  983. void *p ;
  984. {
  985.     extern unsigned Nr_timertype;
  986.  
  987.     if (argc < 2) {
  988.         tprintf("Netrom timer type is %s\n", Nr_timertype ? "linear" : "exponential" ) ;
  989.         return 0 ;
  990.     }
  991.     
  992.     switch (argv[1][0]) {
  993.         case 'l':
  994.         case 'L':
  995.             Nr_timertype = 1 ;
  996.             break ;
  997.         case 'e':
  998.         case 'E':
  999.             Nr_timertype = 0 ;
  1000.             break ;
  1001.         default:
  1002.             tprintf("use: netrom timertype [linear|exponential]\n") ;
  1003.             return -1 ;
  1004.     }
  1005.  
  1006.     return 0 ;
  1007. }
  1008.  
  1009.